package x.ovo.wechat.bot.core.contact;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import x.ovo.wechat.bot.core.Context;
import x.ovo.wechat.bot.core.Manager;
import x.ovo.wechat.bot.core.entity.Contact;
import x.ovo.wechat.bot.core.entity.Member;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * 联系人管理器
 *
 * @author ovo, created by 2024/07/06
 */
public interface ContactManager extends Manager {

    Logger log = LoggerFactory.getLogger(ContactManager.class.getSimpleName());
    Map<RetrievalType, RetrievalStratrgy> STRATRGY_MAP = new HashMap<>(4, 1);


    /**
     * 根据联系人的唯一标识符检索并返回联系人对象。
     *
     * @param id 联系人的唯一标识符。
     * @return {@link Contact} 与给定标识符匹配的联系人对象。
     */
    Contact get(String id);

    /**
     * 根据联系人的唯一标识符和检索类型检索并返回联系人对象。
     *
     * @param id   联系人的唯一标识符。
     * @param type 检索类型，用于指定如何获取联系人信息。
     * @return {@link Contact} 与给定标识符和检索类型匹配的联系人对象。
     */
    Contact get(String id, RetrievalType type);

    /**
     * 根据联系人的唯一标识符移除相应的联系人对象。
     *
     * @param id 要移除的联系人的唯一标识符。
     */
    void remove(String id);

    /**
     * 根据联系人的唯一标识符和检索类型移除联系人对象。
     *
     * @param id   联系人的唯一标识符。
     * @param type 检索类型，用于指定如何移除联系人信息。
     */
    void remove(String id, RetrievalType type);

    /**
     * 同步最近联系人。
     * 将给定的联系人集合同步到联系人列表中。
     *
     * @param contacts 要同步的联系人集合。
     */
    void syncRecent(Collection<Contact> contacts);

    /**
     * 刷新联系人数据。
     * 该方法用于强制刷新联系人的缓存数据，确保数据的即时性。
     */
    void flushContact();

    /**
     * 刷新群组数据。
     * 该方法用于强制刷新群组的缓存数据，确保数据的即时性。
     */
    void flushGroup();

    /**
     * 获取群组成员。
     * 根据群组标识符和成员的唯一标识符以及检索类型，检索并返回群组成员对象。
     *
     * @param group 群组的唯一标识符。
     * @param id    成员的唯一标识符。
     * @param type  检索类型，用于指定如何获取群组成员信息。
     * @return {@link Member} 与给定群组标识符和成员标识符匹配的群组成员对象。
     */
    Member get(String group, String id, RetrievalType type);

    /**
     * 根据群组标识符和成员的唯一标识符和检索类型移除群组成员对象。
     *
     * @param group 群组的唯一标识符。
     * @param id    成员的唯一标识符。
     * @param type  检索类型，用于指定如何移除群组成员信息。
     */
    void remove(String group, String id, RetrievalType type);

    @Override
    default void init() {
        Context.INSTANCE.setContactManager(this);
        log.info("联系人管理器初始化完成");
    }

    /**
     * 刷新联系人和群组缓存
     */
    default void flush() {
        this.flushContact();
        this.flushGroup();
    }

    /**
     * 获取检索策略
     *
     * @param type 检索类型
     * @return {@link RetrievalStratrgy } 指定的检索策略。
     */
    default RetrievalStratrgy getStratrgy(RetrievalType type) {
        return Optional.ofNullable(STRATRGY_MAP.get(type))
                .orElseThrow(() -> new IllegalArgumentException(String.format("未找到检索类型 [%s] 对应的检索策略", type)));
    }
}
